package com.yuexia.yxim.server.handler;

import com.yuexia.yxim.common.bean.msg.ProtoMsg;
import com.yuexia.yxim.common.cocurrent.CallbackTask;
import com.yuexia.yxim.common.cocurrent.CallbackTaskScheduler;
import com.yuexia.yxim.server.processer.LoginProcesser;
import com.yuexia.yxim.server.server.ServerSession;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 登录请求处理器
 * @Author: yue_xia
 * @Date: 2020/6/2 8:45 下午
 */
@Slf4j
@Service
@ChannelHandler.Sharable
public class LoginRequestHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    private LoginProcesser loginProcesser;

    /**
     * 接收到客户端的消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        /*
        * 1.对消息进行必要的判断：
        *   判断是否为登录请求protobuf数据包，如果不是通过super.channelRead(ctx, msg);交给流水线的下一站
        * 2.创建一个serverSession,及为客户端创建一个服务端的会话
        * 3.使用自定义的callbackTaskScheduler异步任务调度器，提交一个异步任务，启动LoginProcesser执行登录用户验证
        * */

        if (msg == null || !(msg instanceof ProtoMsg.Message)) {
            super.channelRead(ctx, msg);
            return;
        }
        ProtoMsg.Message pkg = (ProtoMsg.Message) msg;

        //获取请求类型
        ProtoMsg.HeadType type = pkg.getType();
        if (!type.equals(ProtoMsg.HeadType.LOGIN_REQUEST)) {
            super.channelRead(ctx, msg);
            return;
        }

        ServerSession session = new ServerSession(ctx.channel());

        //异步任务  处理登录的逻辑
        CallbackTaskScheduler.add(new CallbackTask<Boolean>() {
            @Override
            public Boolean execute() throws Exception {
                return loginProcesser.action(session, pkg);
            }

            @Override
            public void onBack(Boolean aBoolean) {
                if (aBoolean) {
                    ctx.pipeline().remove(LoginRequestHandler.this);
                    log.info("登录成功：{}", session.getUser());
                }else{
                    ServerSession.closeSession(ctx);
                    log.error("登录失败:{}", session.getUser());
                }
            }

            @Override
            public void onException(Throwable t) {
                ServerSession.closeSession(ctx);
                log.error("登录失败:{}", session.getUser());
            }
        });


    }
}
